﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;

namespace Wheels.Windows
{
    public class MessageWindow : NativeWindow, IDisposable
    {
#pragma warning disable 1591

        public class MessageArgs : EventArgs
        {
            public Message SourceMessage { get; private set; }
            public Message? Message { get; set; }

            public MessageArgs(Message m)
            {
                SourceMessage = m;
                Message = m;
            }
        }

        public event EventHandler<MessageArgs> Message;

        public MessageWindow()
        {
            CreateHandle(new CreateParams());
        }

        protected override void WndProc(ref Message m)
        {
            if (Message != null)
            {
                var args = new MessageArgs(m);
                Message(this, args);

                if (!args.Message.HasValue)
                    return;
                m = args.Message.Value;
            }

            base.WndProc(ref m);
        }

        #region Disposing

        private volatile bool mIsDisposeCalled = false;
        protected bool IsDisposeCalled { get { return mIsDisposeCalled; } }
        private volatile int mIsDisposeFired = 0;
        protected bool IsDisposeFired { get { return mIsDisposeFired != 0; } }
        private volatile bool mIsDisposed = false;
        public bool IsDisposed { get { return mIsDisposed; } }

        protected virtual void Dispose(bool disposing)
        {
            DestroyHandle();
        }

        private void DoDispose(bool disposing)
        {
            if (disposing)
                mIsDisposeCalled = true;

#pragma warning disable 0420
            if (Interlocked.CompareExchange(ref mIsDisposeFired, 1, 0) != 0)
                return;
#pragma warning restore 0420

            Dispose(disposing);

            if (disposing)
            {
                mIsDisposed = true;
                GC.SuppressFinalize(this);
            }
        }

        public void Dispose()
        {
            DoDispose(true);
        }
        ~MessageWindow()
        {
            DoDispose(false);
        }

        #endregion
    }
}
